/*
    SUSAN® - Sole of Unix Save ANything

   Copyright (C) 2004-2009 Hechzh Property
   Copyright (C) 2016-2016 Skyatlas Co. CN

   
*/
/*
 * Kern Sibbald, July MMIV
 */
/**
 * @file
 * BErrNo header file
 */

#ifndef BAREOS_LIB_BERRNO_H_
#define BAREOS_LIB_BERRNO_H_

#include "lib/berrno.h"
#include "include/bareos.h"

/**
 * Extra bits set to interpret errno value differently from errno
 */
#ifdef HAVE_WIN32
#define b_errno_win32 (1 << 29) /* user reserved bit */
#else
#define b_errno_win32 0 /* On Unix/Linix system */
#endif
#define b_errno_exit (1 << 28)   /* child exited, exit code returned */
#define b_errno_signal (1 << 27) /* child died, signal code returned */

/**
 * A more generalized way of handling errno that works with Unix, Windows,
 *  and with BAREOS bpipes.
 *
 * It works by picking up errno and creating a memory pool buffer
 *  for editing the message. strerror() does the actual editing, and
 *  it is thread safe.
 *
 * If bit 29 in berrno_ is set then it is a Win32 error, and we
 *  must do a GetLastError() to get the error code for formatting.
 * If bit 29 in berrno_ is not set, then it is a Unix errno.
 *
 */
class BErrNo {
  POOLMEM* buf_;
  int berrno_;
  void FormatWin32Message();

 public:
  BErrNo(int pool = PM_EMSG);
  ~BErrNo();
  const char* bstrerror();
  const char* bstrerror(int errnum);
  void SetErrno(int errnum);
  int code() { return berrno_ & ~(b_errno_exit | b_errno_signal); }
  int code(int stat) { return stat & ~(b_errno_exit | b_errno_signal); }
};

/* Constructor */
inline BErrNo::BErrNo(int pool)
{
  berrno_ = errno;
  buf_ = GetPoolMemory(pool);
  *buf_ = 0;
  errno = berrno_;
}

inline BErrNo::~BErrNo() { FreePoolMemory(buf_); }

inline const char* BErrNo::bstrerror(int errnum)
{
  berrno_ = errnum;
  return BErrNo::bstrerror();
}


inline void BErrNo::SetErrno(int errnum) { berrno_ = errnum; }

#endif /* BAREOS_LIB_BERRNO_H_ */
